package com.bwie.orders.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bwie.common.utils.R;
import com.bwie.orders.feignService.GoodsService;
import com.bwie.orders.vo.ActivityVo;
import com.bwie.orders.vo.GoodsVo;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.common.utils.PageUtils;
import com.bwie.common.utils.Query;

import com.bwie.orders.dao.OrderDao;
import com.bwie.orders.entity.OrderEntity;
import com.bwie.orders.service.OrderService;
import org.springframework.transaction.annotation.Transactional;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient client;
    @Autowired
    private RabbitTemplate rabbitTemplate;




    public static final int MACHINE_ID = 1;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }



    //随机生成订单号
    public static String getOrderNumber() {
        int machineId = MACHINE_ID;//随机给个前缀

        //UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        System.out.println("hashCodeV：" + hashCodeV);
        if (hashCodeV < 0) {//有可能是负数,所以判断一下
            hashCodeV = -hashCodeV;
        }

        Date date=new Date();
        //15为长度
        //%0相当于一个占位符，而d就是填充的数据。
        //0是在arr转化为字符后，长度达不到length的时候，前面以0 补足。
        //d是个占位符，会被arr所替换。
        return machineId + String.format("%015d", hashCodeV)+date.getTime();

        //测试数据
        //hashCodeV：238482216
        //10000002384822161645710818379
    }

    @Override
    @Transactional
    public R addOrder(OrderEntity order) {
        //添加订单 下面为默认值
        order.setCreateDate(new Date());
        order.setStatus(0);//订单状态0新建未支付 1已支付 2已发货 3已收货 4已退款 5已完成
        order.setGoodsCount(1);//商品数量默认为1
        order.setGoodsChannel(1);//1.pc 2.android 3.ios
        //随机生成订单编号
        order.setSorder(getOrderNumber());
        //feign查询获取 goods
        R infogoods = goodsService.infogoods(order.getGoodsId());
        GoodsVo goodsVo = infogoods.getData(new TypeReference<GoodsVo>(){});
        //feign获取活动信息 activity
        R infoactive = goodsService.infoactive(order.getActId());
        ActivityVo activityVo = infoactive.getData(new TypeReference<ActivityVo>() {
        });

        //超买问题:比如一个用户针对一个活动只能买一个，但是发下好几个订单，相当于超买》》》》》》》
        //数据库里面创建联合唯一索引，用户id+活动id
      int count= baseMapper.selectOrderId(order.getUserId(),order.getActId());
        if (count>0){
            return R.error("参与过活动并购买过该商品");
        }
        //判断秒杀库存是否大于0 大于0说明有库存，解决库存 超卖》》》》》》》分布式锁》》》》》》》
        if (activityVo.getStockCount()>0){
            //商品库存-1
            goodsVo.setGoodsStock(goodsVo.getGoodsStock()-1);
            //feign调用修改
            goodsService.updateGoodFeign(goodsVo);
            //活动库存-1
            activityVo.setStockCount(activityVo.getStockCount()-1);
            //feign调用修改
            goodsService.updateActFeign(activityVo);

               //生成订单
               orderDao.insert(order);

            //秒杀成功
            return R.ok().setData(order.getOrderId());
        }else {//库存没了

            return R.error("秒杀失败");
        }

    }
    //方法2
    @Override
    public R addOrder2(OrderEntity order, String path)  {

        RLock lock = client.getLock("lock");
        try {
            //n b = lock.tryLock(10,10, TimeUnit.MILLISECONDS);
            lock.lock();   //判断传入的商品id和用户id不为null
        //feign获取活动信息 activity
        R infoactive = goodsService.infoactive(order.getActId());
        ActivityVo activityVo = infoactive.getData(new TypeReference<ActivityVo>() {
        });
        //feign查询获取 goods
        R infogoods = goodsService.infogoods(order.getGoodsId());
        GoodsVo goodsVo = infogoods.getData(new TypeReference<GoodsVo>(){});

        if (activityVo.getStockCount()==0){
            return R.error("秒杀失败,库存不足");
        }
//        int count= baseMapper.selectOrderId(order.getUserId(),order.getActId());
        Integer count = (Integer) redisTemplate.opsForValue().get(order.getUserId() + "and" + order.getActId());
        if (count!=null&&count>0){
            return R.error("参与过活动并购买过该商品");
        }

                //添加订单 下面为默认值
                order.setCreateDate(new Date());
                order.setStatus(0);//订单状态0新建未支付 1已支付 2已发货 3已收货 4已退款 5已完成
                order.setGoodsCount(1);//商品数量默认为1
                order.setGoodsChannel(1);//1.pc 2.android 3.ios
                //随机生成订单编号
                order.setSorder(getOrderNumber());
//                //商品库存-1
//                goodsVo.setGoodsStock(goodsVo.getGoodsStock()-1);
//                //feign调用修改
//                goodsService.updateGoodFeign(goodsVo);
                //活动库存-1
                activityVo.setStockCount(activityVo.getStockCount()-1);
                //feign调用修改
                goodsService.updateActFeign(activityVo);
//                //将库存放入 redis
//            redisTemplate.boundHashOps("stockCount").put("count"+activityVo.getActId(),activityVo);
//            redisTemplate.boundHashOps("stockCount").get("count"+activityVo.getActId());

            redisTemplate.opsForValue().set(order.getUserId()+"and"+order.getActId(),1,activityVo.getEndDate().getTime()-new Date().getTime(),TimeUnit.MILLISECONDS);
                //----------------------MQ---------------------------------
                //使用rabbitMQ生成订单
                rabbitTemplate.convertAndSend("miaosha","add.order", JSON.toJSONString(order));
                //orderDao.insert(order);
                //秒杀成功
                return R.ok().setData(order.getOrderId());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (lock.isLocked()){
                if(lock.isHeldByCurrentThread()){
                    lock.unlock();
                }
            }
        }

        return null;
    }

    @Override
    public R updateOrder(Map<String, String> params) {
        //确认订单编号
        String orderSorder = params.get("out_trade_no");
        //根据订单编号获取订单信息
        OrderEntity orderEntity = baseMapper.selectOne(new QueryWrapper<OrderEntity>().eq("sorder", orderSorder));
        //判断金额
        String totalAmount = params.get("total_amount");
        if (orderEntity.getGoodsPrice().doubleValue()==Double.valueOf(totalAmount)){
            //修改订单的状态为已支付
            orderEntity.setStatus(1);
            orderEntity.setPayDate(new Date());
            baseMapper.updateById(orderEntity);
            //
            return R.ok("支付完成");
        }

        return R.error(500,"金额有误");
    }


}